#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <pthread.h>

typedef struct strut{
	mpf_t x;
	mpf_t xi;
	mpf_t xr;
	mpf_t y;
	mpf_t yi;
	mpf_t z;
	mpf_t aux;
} strut;

strut borwein;

pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mut3 = PTHREAD_MUTEX_INITIALIZER;

void parcelax ( strut *borwein){
	
	pthread_mutex_lock(&mut1);
	
	mpf_ui_div(borwein->xi,1,borwein->xr);
        mpf_add(borwein->xi,borwein->xr,borwein->xi);
        mpf_div_ui(borwein->xi,borwein->xi,2);

        pthread_mutex_unlock(&mut1);  
}


void parcelay ( strut *borwein){

	pthread_mutex_lock(&mut2);
		
	mpf_add_ui(borwein->yi,borwein->y,1);
        mpf_mul(borwein->yi,borwein->xr,borwein->yi);
        mpf_add(borwein->aux,borwein->x,borwein->y);        
        mpf_div(borwein->yi,borwein->yi,borwein->aux);                      
        pthread_mutex_unlock(&mut2);  
}

void parcelaz ( strut *borwein){
	
        pthread_mutex_lock(&mut3);

        mpf_add_ui(borwein->aux,borwein->xi,1);
        mpf_mul(borwein->aux,borwein->z,borwein->aux);
        mpf_mul(borwein->aux,borwein->aux,borwein->yi);
        mpf_add_ui(borwein->z,borwein->yi,1);     
        mpf_div(borwein->z,borwein->aux,borwein->z);
        
        pthread_mutex_unlock(&mut3);  
}


int main (void){

        
	pthread_t t1,t2,t3;
        int iteracao;
        clock_t start,end;
    	FILE *fp;
        float desempenho;
    
        mpf_set_default_prec(33219281);

        mpf_init(borwein.xr);
        mpf_init(borwein.x);
        mpf_init(borwein.xi);
        mpf_init(borwein.y);
        mpf_init(borwein.yi);
        mpf_init(borwein.z);
        mpf_init(borwein.aux);      
        mpf_sqrt_ui(borwein.xi,2);
        mpf_add_ui(borwein.z,borwein.xi,2);

	start = clock(); 

        for(iteracao=0; iteracao <= 24; iteracao++){
                
                mpf_set(borwein.x,borwein.xi);    
                mpf_set(borwein.y,borwein.yi);    
                mpf_sqrt(borwein.xr,borwein.x);
        
                pthread_create(&t1, NULL, (void*)parcelax,&borwein);
                pthread_create(&t2, NULL, (void*)parcelay,&borwein);
                
                pthread_join(t1,NULL);
                pthread_join(t2,NULL);
        
                
                pthread_create(&t3, NULL, (void*)parcelaz,&borwein);
                pthread_join(t3,NULL);
        
                
        //       if(iteracao == 24)
	//	fp = fopen("pi_concorrente.txt", "w");
          //     else fp = fopen("valores_pi_concorrente.txt","a+"); 
		//if(fp == NULL){
                  //  printf("Problema ao abrir o arquivo");
                    //return 1;
                //}
       	//if(iteracao == 24)
	// gmp_fprintf(fp, "%.10000000Ff", borwein.z);
	//else gmp_fprintf(fp, "%.100Ff\n", borwein.z);
        //	fclose(fp);
        }
        
    end = clock();

        desempenho = ((double)(end-start)/CLOCKS_PER_SEC);

        fp = fopen("Tempo_paralelo.txt","w"); 
	if(fp == NULL){
            printf("Erro ao abrir o arquivo");
            return 1;
        }
        fprintf(fp,"Concurrent Borwein : %.10f segundos.\n",desempenho);
        fclose(fp);

        
        mpf_clear(borwein.xr);
        mpf_clear(borwein.x);
        mpf_clear(borwein.xi);
        mpf_clear(borwein.y);
        mpf_clear(borwein.yi);
        mpf_clear(borwein.z);
        mpf_clear(borwein.aux);

        pthread_mutex_destroy(&mut1);
        pthread_mutex_destroy(&mut2);
        pthread_mutex_destroy(&mut3);

        pthread_exit(NULL);

        return 0;

}
